#ifndef _TME_API_H_
#define _TME_API_H_

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/* 常见返回错误码 */
typedef enum {
    TME_STATE_CODE_PARAM = -6, /* 参数错误 */
    TME_STATE_CODE_MMAP = -5, /* 内存映射失败 */
    TME_STATE_CODE_FILE = -3, /* 读/写/创建文件失败 */
    TME_STATE_CODE_ALLOC = -2, /* 分配内存失败 */
    TME_STATE_CODE_FAILED = -1, /* 失败 */
    TME_STATE_CODE_OK = 0,
} TME_ERROR_CODE;

/* 属性全名时,用于间隔父属性的分隔符 */
#define TME_ATTR_FULL_NAME_SPILT ':'

/*
 *  数据回调
 *  参数:
 *      handle: 文件句柄
 *      attrId: 属性id
 *      timeOffsetMs: 实践戳
 */
typedef void(*TME_DATA_CALLBACK)(void* handle, int32_t attrId, uint32_t timeOffsetMs, const void* data, int32_t dataSize, void* priv);

/* -------------------- 公共api -------------------- */

/* 打开文件 */
void* tme_open(const char* file);
/* 只读模式打开(保护文件不被修改) */
void* tme_openReadOnly(const char* file);
/* 关闭 */
void tme_close(void* handle);

/* 打印文件信息,返回长度 */
int32_t tme_info(void* handle, char* buff, int32_t buffSize);

/* 是否只读 0/否 其它/是 */
int32_t tme_isReadOnly(void* handle);

/* 根据名称获取属性id,返回<=0失败 */
int32_t tme_attrGetId(void* handle, const char* attrName);
/* 遍历获取所有属性id,count从0数起,返回<=0结束 */
int32_t tme_attrGetIdLoop(void* handle, int32_t count);
/* 根据id获取属性名称,成功返回0 */
int32_t tme_attrGetName(void* handle, int32_t attrId, char* buff, int32_t buffSize);
/* 返回多级属性名,成功返回0,格式如:"父属性1:父属性2:当前属性名" */
int32_t tme_attrGetFullName(void* handle, int32_t attrId, char* buff, int32_t buffSize);

/* -------------------- 写数据api -------------------- */

/* 
 *  创建属性
 *  参数:
 *      handle: 文件句柄
 *      attrName: 属性名称,带父属性时写作"父属性名:当前属性名"
 *      checkUnique: 检查属性唯一,否则报错 0/关 1/开
 *  返回:
 *      成功返回大于等于0的 attrId
 */
int32_t tme_attrAdd(void* handle, const char* attrName, int32_t checkUnique);

/* 
 *  写属性
 *  参数:
 *      handle: 文件句柄
 *      attrId: 属性id
 *      attrName: 属性名称
 *      data,dataSize: 数据
 *  返回:
 *      成功返回写入数据量
 */
int32_t tme_attrWrite(void* handle, int32_t attrId, const void* data, int32_t dataSize);
int32_t tme_attrWriteByName(void* handle, const char* attrName, const void* data, int32_t dataSize);

/* -------------------- 读数据api -------------------- */

/* 
 *  读属性
 *  参数:
 *      handle: 文件句柄
 *      attrId: 属性id
 *      attrName: 属性名称
 *      data,dataSize: 数据
 *      offset: 传入&返回当前读取位置
 *  返回:
 *      成功返回读取数据量
 */
int32_t tme_attrRead(void* handle, int32_t attrId, void* data, int32_t dataSize, int32_t *offset);
int32_t tme_attrReadByName(void* handle, const char* attrName, void* data, int32_t dataSize, int32_t *offset);

/* 返回属性数据总大小 */
int32_t tme_attrSizeOf(void* handle, int32_t attrId);

/* -------------------- 读时间表api -------------------- */

/* 记录时间表局部信息的节点链表结构 */
typedef struct TME_TimeNode {
    /* 时:分:秒:毫秒 */
    int32_t tHour;
    int32_t tMin;
    int32_t tSec;
    int32_t tMill;
    /* 与文件创建时间的时差ms */
    int32_t diffMs;
    /* 属性id,名称 */
    int32_t attrId;
    const char* attrName; /* 该内存来自文件handle,如果文件已被关闭则不能再访问该指针 */
    /* 数据起始,长度 */
    int32_t dataOffset;
    int32_t dataLen;
    /* 双向链表 */
    struct TME_TimeNode* next;
    struct TME_TimeNode* prev;
} TME_TimeNode;

/*
 *  读时间节点
 *  参数:
 *      handle: 文件句柄
 *      node: 节点链表载体(自动分配&释放内存)
 *      nodeMax: 最多要读取几个节点,小于等于0表示不限
 *      singleDurationMs: 单个节点数据时长,小于等于0表示不限(即按单次写入算一个节点)
 *      totalDurationMs: 读取时间表时长,和nodeMax谁先满足都立即结束读取
 *      offset: 传入&返回当前读取位置
 *  返回:
 *      成功返回读取节点数
 */
int32_t tme_timeNodeRead(void* handle, TME_TimeNode** node, int32_t nodeMax, int32_t singleDurationMs, int32_t totalDurationMs, int32_t *offset);

/* 释放上面接口取得的链表 */
void tme_timeNodeRelease(TME_TimeNode** node);

/* 根据上面offset,取得当前时间位置(相对文件创建时间增量ms),错误返回负值 */
int32_t tme_timeNodeTimeOf(void* handle, int32_t offset);

/* 按与文件创建时间差值,移动时间轴,成功返回0 */
int32_t tme_timeNodeSeek(void* handle, int32_t offsetTimeMs, int32_t* offset);

#ifdef __cplusplus
}
#endif

#endif // _TME_API_H_
